|
ARD2
RC2
Airbag Reference Demonstrator using MPC5604P
|
00001 00016 #include "Compile_Options.h" 00017 #include "derivative.h" 00018 #include "utils.h" /* For Copy Array */ 00019 #include "flash.h" 00020 /* 00021 ****************************************************************************** 00022 * constants 00023 ****************************************************************************** 00024 */ 00025 /* 00026 ****************************************************************************** 00027 * Globals 00028 ****************************************************************************** 00029 */ 00030 /* 00031 ****************************************************************************** 00032 * u8fnFlashWriteDataFromRAM 00033 ****************************************************************************** 00034 */ 00035 static uint8_t u8fnFlashWriteDataFromRAM(uint32_t* pu32AddressToWrite, \ 00036 uint32_t* pu32ValueToWrite, \ 00037 Flash_t ptFlashInstance, \ 00038 uint8_t u8TwoContiguousWords) 00039 { 00040 uint8_t u8Status; 00041 uint16_t u16TimeOut; 00042 00043 u8Status = CLEAR; 00044 u16TimeOut = CLEAR; 00045 00046 /* The first instruction selects the desired operation by setting its */ 00047 /* corresponding selection bit in MCR */ 00048 ptFlashInstance->MCR.B.PGM = TRUE; 00049 00050 /* Next, write to the location so that the flash controller takes the */ 00051 /* values. */ 00052 *pu32AddressToWrite = *pu32ValueToWrite; 00053 if(TRUE == u8TwoContiguousWords) 00054 { 00055 *(++pu32AddressToWrite) = *(++pu32ValueToWrite); 00056 } 00057 else 00058 { 00059 /* Nothing */ 00060 } 00061 00062 /* Set MCR[EHV] to 1 to start the internal program sequence */ 00063 ptFlashInstance->MCR.B.EHV = TRUE; 00064 00065 /* Wait for the programming to be done */ 00066 do 00067 { 00068 u16TimeOut++; 00069 }while((CLEAR == ptFlashInstance->MCR.B.DONE) && \ 00070 (FLASHING_TIMEOUT > u16TimeOut)); 00071 00072 if(FLASHING_TIMEOUT == u16TimeOut) 00073 { 00074 /* We timed-out. We need to flag this */ 00075 u8Status = STATUS_FLASHING_TIME_OUT; 00076 } 00077 else 00078 { 00079 /* Nothing happened */ 00080 } 00081 /* Confirm MCR[PEG] = 1. */ 00082 if(TRUE != ptFlashInstance->MCR.B.PEG) 00083 { 00084 /* Set a flag */ 00085 u8Status = STATUS_PROGRAMMED_WRONG; 00086 } 00087 else 00088 { 00089 /* We are happy */ 00090 } 00091 00092 /* Write a logic 0 to the MCR[EHV] bit. */ 00093 ptFlashInstance->MCR.B.EHV = CLEAR; 00094 /* Write a logic 0 to the MCR[PGM] bit to terminate the program operation */ 00095 ptFlashInstance->MCR.B.PGM = CLEAR; 00096 00097 return(u8Status); 00098 } 00099 /* 00100 ****************************************************************************** 00101 * u8fnFlashEraseFromRAM 00102 ****************************************************************************** 00103 */ 00104 static uint8_t u8fnFlashEraseFromRAM(Flash_t ptFlashInstance, uint32_t u32LMS) 00105 { 00106 uint8_t u8Status; 00107 uint32_t u32TimeOut; 00108 00109 u8Status = CLEAR; 00110 u32TimeOut = CLEAR; 00111 00112 /* 1. Change the value in the MCR[ERS] bit from 0 to 1. */ 00113 ptFlashInstance->MCR.B.ERS = TRUE; 00114 00115 /* According to the spec, start by selecting sectors that will be erased */ 00116 ptFlashInstance->LMS.R = u32LMS; 00117 00118 /* Write to any address in flash. This is referred to as an erase */ 00119 /* interlock write. */ 00120 *(uint32_t*)DATA_FLASH_F3_SECTOR_MIN = CLEAR; 00121 *(uint32_t*)CODE_FLASH_F3_SECTOR_MIN = CLEAR; 00122 00123 /* Set MCR[EHV] to start the internal erase sequence */ 00124 ptFlashInstance->MCR.B.EHV = TRUE; 00125 00126 u32TimeOut = CLEAR; 00127 /* Wait for the operation to be done */ 00128 do 00129 { 00130 u32TimeOut++; 00131 }while((CLEAR == ptFlashInstance->MCR.B.DONE) && \ 00132 (ERASING_TIMEOUT > u32TimeOut)); 00133 00134 if(ERASING_TIMEOUT == u32TimeOut) 00135 { 00136 /* We timed-out. We need to flag this */ 00137 u8Status = STATUS_FLASHING_TIME_OUT; 00138 } 00139 else 00140 { 00141 /* Nothing happened */ 00142 } 00143 00144 /* Confirm MCR[PEG] = 1. */ 00145 if(TRUE != ptFlashInstance->MCR.B.PEG) 00146 { 00147 /* Set a flag */ 00148 u8Status = STATUS_PROGRAMMED_WRONG; 00149 } 00150 else 00151 { 00152 /* We are happy */ 00153 } 00154 /* Write a logic 0 to the MCR[EHV] bit. */ 00155 ptFlashInstance->MCR.B.EHV = CLEAR; 00156 00157 /* Write a logic 0 to the MCR[ERS] bit to terminate the program operation */ 00158 ptFlashInstance->MCR.B.ERS = CLEAR; 00159 00160 return(u8Status); 00161 } 00162 /* 00163 ****************************************************************************** 00164 * vfnFlashArray 00165 ****************************************************************************** 00166 */ 00167 uint8_t u8fnFlashWrite(uint32_t* pu32Source, uint32_t* pu32Destination, \ 00168 uint16_t u16Size) 00169 { 00170 Flash_t ptFlashInstance; 00171 uint8_t u8Status; 00172 uint8_t u8Sector; 00173 uint8_t u8TwoBytesAtOnce; 00174 00175 /* Init local variables and select flash instance */ 00176 u8Status = CLEAR; 00177 u8Sector = CLEAR; 00178 u8TwoBytesAtOnce = CLEAR; 00179 ptFlashInstance = tfnFlashSelectInstance(\ 00180 u8fnReturnTypeOfFlash(\ 00181 (uint32_t)(pu32Destination + u16Size))); 00182 /* If we still have a valid instance */ 00183 if(CLEAR != ptFlashInstance) 00184 { 00185 /* Clear the lock - this is a write-once per reset operation. */ 00186 /* In the spec, p. 379, 382, passwords are defined for editing LML */ 00187 /* and SLL. These are written here first. */ 00188 ptFlashInstance->LML.R = FLASH_PRIMARY_LOCK_KEY; 00189 ptFlashInstance->LML.R = FLASH_ALLOW_COMPLETE_REFLASH; 00190 ptFlashInstance->SLL.R = FLASH_SECONDARY_LOCK_KEY; 00191 ptFlashInstance->SLL.R = FLASH_ALLOW_COMPLETE_REFLASH; 00192 00193 /* Copy the flashing routine to RAM from where we will execute */ 00194 vfnCopyArray((uint8_t*)&u8fnFlashWriteDataFromRAM, \ 00195 (uint8_t*)RAM_ADDRESS_FOR_FLASHING_ROUTINE, 00196 FLASH_ROUTINE_SIZE); 00197 00198 for(; u16Size > CLEAR; u16Size--) 00199 { 00200 if(NOT_FLASHABLE != u8Sector) 00201 { 00202 /* If we can flash, let's see if we're writing one or two words at */ 00203 /* the same time. This is a hardware capability. */ 00204 if(1u < u16Size) 00205 { 00206 /* If BIT3 is clear we know that the destination address will is */ 00207 /* at the start of a 64-bit register, and therefore we can flash */ 00208 /* two 32-bit words at once. */ 00209 if((uint32_t)pu32Destination & BIT3) 00210 { 00211 u8TwoBytesAtOnce = CLEAR; 00212 } 00213 else 00214 { 00215 u8TwoBytesAtOnce = TRUE; 00216 } 00217 } 00218 else 00219 { 00220 u8TwoBytesAtOnce = CLEAR; 00221 } 00222 00223 /* Now, let's actually program by jumping into RAM. */ 00224 u8Status |= PROGRAM(pu32Destination, pu32Source, ptFlashInstance, u8TwoBytesAtOnce); 00225 } /* end if */ 00226 else 00227 { 00228 u8Status = u8Sector; 00229 } 00230 00231 /* Let's Increment our pointers coherently with how many values were */ 00232 /* flashed */ 00233 pu32Destination += (1 + u8TwoBytesAtOnce); 00234 pu32Source += (1 + u8TwoBytesAtOnce); 00235 00236 /* Also, don't forget to decrement size manually if two words were */ 00237 /* flashed. */ 00238 u16Size -= u8TwoBytesAtOnce; 00239 00240 }/* End For */ 00241 } /* end if memory locations are valid */ 00242 else 00243 { 00244 u8Status = NOT_FLASHABLE; 00245 } 00246 return(u8Status); 00247 } 00248 /* 00249 ****************************************************************************** 00250 * u8fnFlashErase 00251 ****************************************************************************** 00252 */ 00253 uint8_t u8fnFlashErase(uint32_t* pu32DataToErase) 00254 { 00255 uint8_t u8Status; 00256 uint8_t u8TypeOfFlash; 00257 uint8_t u8FlashSector; 00258 uint32_t u32LMS; 00259 Flash_t ptMyFlash; 00260 00261 /* Init locals */ 00262 u8Status = CLEAR; 00263 u8FlashSector = CLEAR; 00264 u32LMS = CLEAR; 00265 00266 /* Figure out what module we will be erasing */ 00267 u8TypeOfFlash = u8fnReturnTypeOfFlash((uint32_t)pu32DataToErase); 00268 00269 if(DATA_FLASH == u8TypeOfFlash) 00270 { 00271 /* Define instance as Data flash. */ 00272 ptMyFlash = (Flash_t)&DFLASH; 00273 u8FlashSector = u8fnReturnDataFlashSector((uint32_t)pu32DataToErase); 00274 } 00275 else if(CODE_FLASH == u8TypeOfFlash) 00276 { 00277 /* Define instance as Code flash. */ 00278 ptMyFlash = &CFLASH; 00279 u8FlashSector = u8fnReturnCodeFlashSector((uint32_t)pu32DataToErase); 00280 } 00281 else 00282 { 00283 u8Status = NOT_FLASHABLE; 00284 } 00285 00286 if(CLEAR == u8Status) 00287 { 00288 if(NOT_FLASHABLE != u8FlashSector) 00289 { 00290 /* Clear the lock - this is a write-once per reset operation. */ 00291 /* In the spec, p. 379, 382, passwords are defined for editing LML */ 00292 /* and SLL. These are written here first. */ 00293 ptMyFlash->LML.R = FLASH_PRIMARY_LOCK_KEY; 00294 ptMyFlash->LML.R = FLASH_ALLOW_COMPLETE_REFLASH; 00295 ptMyFlash->SLL.R = FLASH_SECONDARY_LOCK_KEY; 00296 ptMyFlash->SLL.R = FLASH_ALLOW_COMPLETE_REFLASH; 00297 00298 /* Copy the erase routine to RAM from where we will execute */ 00299 vfnCopyArray((uint8_t*)&u8fnFlashEraseFromRAM, \ 00300 (uint8_t*)RAM_ADDRESS_FOR_FLASHING_ROUTINE, 00301 ERASE_ROUTINE_SIZE); 00302 /* Figure out what LMS bits will be set - this is directly mapped */ 00303 /* to Hardware. */ 00304 u32LMS = u32fnFlashSectorToLMS(u8FlashSector); 00305 00306 /* Now ERASE!! */ 00307 u8Status = ERASE(ptMyFlash, u32LMS); 00308 00309 } 00310 else 00311 { 00312 u8Status = NOT_FLASHABLE; 00313 } 00314 } 00315 else 00316 { 00317 /* Already flagged - exit */ 00318 } 00319 00320 return(u8Status); 00321 } 00322 /* 00323 ****************************************************************************** 00324 * u8fnReturnTypeOfFlash 00325 ****************************************************************************** 00326 */ 00327 static uint8_t u8fnReturnTypeOfFlash(uint32_t u32Location) 00328 { 00329 uint8_t u8Status; 00330 00331 u8Status = CLEAR; 00332 00333 if((CODE_FLASH_ARRAY_0_TOP_ADDRESS >= u32Location) && \ 00334 (CODE_FLASH_ARRAY_0_MIN_ADDRESS <= u32Location)) 00335 { 00336 u8Status = CODE_FLASH; 00337 } 00338 else if((CODE_FLASH_ARRAY_0_SHADOW_TOP_ADDRESS >= u32Location) && \ 00339 (CODE_FLASH_ARRAY_0_SHADOW_MIN_ADDRESS <= u32Location)) 00340 { 00341 u8Status = CODE_FLASH_SHADOW; 00342 } 00343 else if((DATA_FLASH_ARRAY_0_TOP_ADDRESS >= u32Location) && \ 00344 (DATA_FLASH_ARRAY_0_MIN_ADDRESS <= u32Location)) 00345 { 00346 u8Status = DATA_FLASH; 00347 } 00348 else 00349 { 00350 u8Status = NOT_FLASHABLE; 00351 } 00352 00353 return(u8Status); 00354 } 00355 /* 00356 ****************************************************************************** 00357 * tfnFlashSelectInstance 00358 ****************************************************************************** 00359 */ 00360 static Flash_t tfnFlashSelectInstance(uint8_t u8Instance) 00361 { 00362 Flash_t ptFlashInstance; 00363 if(CODE_FLASH == u8Instance) 00364 { 00365 ptFlashInstance = &CFLASH; 00366 } 00367 else if(DATA_FLASH == u8Instance) 00368 { 00369 ptFlashInstance = (Flash_t)&DFLASH; 00370 } 00371 else 00372 { 00373 ptFlashInstance = CLEAR; 00374 } 00375 00376 return(ptFlashInstance); 00377 } 00378 /* 00379 ****************************************************************************** 00380 * u8fnFlashReadBackInstance 00381 ****************************************************************************** 00382 */ 00383 static uint8_t u8fnFlashReadBackInstance(Flash_t ptFlashInstance) 00384 { 00385 uint8_t u8FlashInstance; 00386 if(ptFlashInstance == &CFLASH) 00387 { 00388 u8FlashInstance = CODE_FLASH; 00389 } 00390 else if(ptFlashInstance == (Flash_t)&DFLASH) 00391 { 00392 u8FlashInstance = DATA_FLASH; 00393 } 00394 else 00395 { 00396 u8FlashInstance = NOT_FLASHABLE; 00397 } 00398 00399 return(u8FlashInstance); 00400 } 00401 /* 00402 ****************************************************************************** 00403 * u8fnReturnCodeFlashSector 00404 ****************************************************************************** 00405 */ 00406 static uint8_t u8fnReturnCodeFlashSector(uint32_t u32Address) 00407 { 00408 uint8_t u8Status; 00409 00410 u8Status = CLEAR; 00411 00412 /* This should only be true if the passed address is in the valid region */ 00413 if(CODE_FLASH_ARRAY_0_TOP_ADDRESS >= u32Address) 00414 { 00415 if(CODE_FLASH_F1_SECTOR_MIN > u32Address) 00416 { 00417 u8Status = F0; 00418 } 00419 else if(CODE_FLASH_F2_SECTOR_MIN > u32Address) 00420 { 00421 u8Status = F1; 00422 } 00423 else if(CODE_FLASH_F3_SECTOR_MIN > u32Address) 00424 { 00425 u8Status = F2; 00426 } 00427 else if(CODE_FLASH_F4_SECTOR_MIN > u32Address) 00428 { 00429 u8Status = F3; 00430 } 00431 else if(CODE_FLASH_F5_SECTOR_MIN > u32Address) 00432 { 00433 u8Status = F4; 00434 } 00435 else if(CODE_FLASH_F6_SECTOR_MIN > u32Address) 00436 { 00437 u8Status = F5; 00438 } 00439 else if(CODE_FLASH_F7_SECTOR_MIN > u32Address) 00440 { 00441 u8Status = F6; 00442 } 00443 else if(CODE_FLASH_F7_SECTOR_MAX >= u32Address) 00444 { 00445 u8Status = F7; 00446 } 00447 else 00448 { 00449 u8Status = NOT_FLASHABLE; 00450 } 00451 } 00452 else 00453 { 00454 u8Status = NOT_FLASHABLE; 00455 } 00456 00457 return(u8Status); 00458 } 00459 /* 00460 ****************************************************************************** 00461 * u8fnReturnTypeOfFlash 00462 ****************************************************************************** 00463 */ 00464 static uint8_t u8fnReturnDataFlashSector(uint32_t u32Address) 00465 { 00466 uint8_t u8Status; 00467 00468 u8Status = CLEAR; 00469 00470 /* This should only be true if the passed address is in the valid region */ 00471 if(DATA_FLASH_F0_SECTOR_MIN <= u32Address) 00472 { 00473 u32Address -= DATA_FLASH_F0_SECTOR_MIN; 00474 u8Status = (uint8_t)(u32Address / DATA_FLASH_SECTOR_SIZE); 00475 } 00476 else 00477 { 00478 u8Status = NOT_FLASHABLE; 00479 } 00480 00481 return(u8Status); 00482 } 00483 /* 00484 ****************************************************************************** 00485 * u8fnFlashSectorToLMS 00486 ****************************************************************************** 00487 */ 00488 static uint32_t u32fnFlashSectorToLMS(uint8_t u8Sector) 00489 { 00490 uint32_t u32LMS; 00491 00492 u32LMS = CLEAR; 00493 00494 /* Start with Mid address spaces */ 00495 if(F6 <= u8Sector) 00496 { 00497 /* Set the corresponding bits for MSL within LMS - Bits 14 + 15 according */ 00498 /* to spec. */ 00499 u32LMS = (1u << ((u8Sector - F6) + BITS_IN_16)); 00500 } 00501 else 00502 { 00503 u32LMS = (1u << u8Sector); 00504 } 00505 00506 return(u32LMS); 00507 } 00508 /* 00509 ****************************************************************************** 00510 * 00511 * End of file. 00512 * 00513 ****************************************************************************** 00514 */